from rest_framework.parsers import MultiPartParser, FormParser
from django.contrib.auth.models import User
from rest_framework import status, viewsets
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.authtoken.models import Token
from rest_framework.permissions import AllowAny
from django.contrib.auth.hashers import make_password
from django.db.models import Q # 导入Q查询.作用: Q 对象用于复杂的查询条件。它允许使用 AND、OR 和 NOT 逻辑操作符来构建更复杂的查询。
from django.conf import settings
import base64
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
import json # 导入json模块
import os
import uuid
import hashlib # 导入哈希库。作用: hashlib 模块提供了多种哈希算法（如 SHA1、SHA256、MD5），用于加密和验证数据的完整性。
import openpyxl
from datetime import datetime
from .serializers import UserSerializer,UserRegisterSerializer
from Users.models import User

from django.shortcuts import render
import logging  # 需要导入 logging 模块
import random
import string
import pandas as pd

from django.http import HttpResponse, JsonResponse
from django.contrib.auth import authenticate, login



# 第二次定稿

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def list(self, request, *args, **kwargs):
        try:
            queryset = self.get_queryset()
            serializer = self.get_serializer(queryset, many=True)
            return Response({'code': 1, 'data': serializer.data})
        except Exception as e:
            return Response({'code': 0, 'msg': "获取用户信息出现异常，具体错误：" + str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def create(self, request, *args, **kwargs):
        try:
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            self.perform_create(serializer)
            return Response({'code':1,'msg': '增加成功'}, status=status.HTTP_201_CREATED)
        except Exception as e:
            return Response({'code': 0, 'msg': "添加到数据库出现异常，具体原因：" + str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def update(self, request, *args, **kwargs):
        try:
            partial = kwargs.pop('partial', False)
            instance = self.get_object()
            serializer = self.get_serializer(instance, data=request.data, partial=partial)
            serializer.is_valid(raise_exception=True)
            self.perform_update(serializer)
            return Response({'code':1,'msg': '更新成功'})
        except Exception as e:
            return Response({'code': 0, 'msg': "修改保存到数据库出现异常，具体原因：" + str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def destroy(self, request, *args, **kwargs):
        try:
            instance = self.get_object()
            self.perform_destroy(instance)
            return Response({'code':1,'msg': '删除成功'})
        except Exception as e:
            return Response({'code': 0, 'msg': "删除检测信息出现异常，具体原因：" + str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def perform_create(self, serializer):
        serializer.save()

    def perform_update(self, serializer):
        serializer.save()

    def perform_destroy(self, instance):
        instance.delete()

class QueryUserAPIView(APIView):
    def post(self, request):
        try:
            data = json.loads(request.body.decode('utf-8'))
            inputstr = data.get('inputstr', '')

            if not inputstr:
                return JsonResponse({'code': 0, 'msg': '查询条件不能为空'})

            obj_user = User.objects.filter(
                Q(username__icontains=inputstr) |
                Q(email__icontains=inputstr) |
                Q(phone__icontains=inputstr) |
                Q(first_name__icontains=inputstr) |
                Q(last_name__icontains=inputstr)  |
                Q(gender=inputstr) 
            ).values()

            user = list(obj_user)
            return JsonResponse({'code': 1, 'data': user})
        except json.JSONDecodeError:
            return JsonResponse({'code': 0, 'msg': '请求数据格式错误'})
        except Exception as e:
            return JsonResponse({'code': 0, 'msg': "查询检测信息出现异常，具体错误：" + str(e)})

class IsExistsUsernameAPIView(APIView):
    def post(self, request):
        try:
            data = json.loads(request.body.decode('utf-8'))
            username = data.get('username', '')

            if not username:
                return JsonResponse({'code': 0, 'msg': '用户名不能为空'})

            exists = User.objects.filter(username=username).exists()
            return JsonResponse({'code': 1, 'exists': exists})
        except Exception as e:
            return JsonResponse({'code': 0, 'msg': "校验用户名失败，具体原因：" + str(e)})

# class ImportUsersExcelView(APIView):
#     parser_classes = [MultiPartParser]

#     def get_random_str(self, length=8):
#         """生成指定长度的随机字符串"""
#         letters = string.ascii_letters + string.digits
#         return ''.join(random.choice(letters) for i in range(length))

#     def read_excel_dict(self, file_path):
#         """读取Excel文件并转换为字典列表"""
#         df = pd.read_excel(file_path)
#         return df.to_dict(orient='records')

#     def post(self, request):
#         rev_file = request.FILES.get('excel')
#         if not rev_file:
#             return JsonResponse({'code': 0, 'msg': '未选择任何文件！'})

#         new_name = self.get_random_str()
#         file_path = os.path.join(settings.MEDIA_ROOT, new_name + os.path.splitext(rev_file.name)[1])
        
#         try:
#             with open(file_path, 'wb') as f:
#                 for chunk in rev_file.chunks():
#                     f.write(chunk)
#         except Exception as e:
#             return JsonResponse({'code': 0, 'msg': str(e)})

#         try:
#             ex_users = self.read_excel_dict(file_path)
#         except Exception as e:
#             return JsonResponse({'code': 0, 'msg': '读取Excel文件失败，具体原因：' + str(e)})

class ImportUsersExcelView(APIView):
    parser_classes = [MultiPartParser]

    def post(self, request):
        rev_file = request.FILES.get('excel')
        if not rev_file:
            return JsonResponse({'code': 0, 'msg': 'Excel文件不存在！'})

        new_name = get_random_str()
        file_path = os.path.join(settings.MEDIA_ROOT, new_name + os.path.splitext(rev_file.name)[1])
        try:
            with open(file_path, 'wb') as f:
                for chunk in rev_file.chunks():
                    f.write(chunk)
        except Exception as e:
            return JsonResponse({'code': 0, 'msg': str(e)})

        try:
            ex_users = read_excel_dict(file_path)
        except Exception as e:
            return JsonResponse({'code': 0, 'msg': '读取Excel文件失败，具体原因：' + str(e)})

        success = 0
        error = 0
        error_usernames = []

        for one_user in ex_users:
            try:
                User.objects.create(
                    username=one_user['username'],
                    email=one_user['email'],
                    phone=one_user['phone'],
                    first_name=one_user['first_name'],
                    last_name=one_user['last_name'],
                    gender=one_user['gender'],
                    created_at=one_user['created_at'],
                    updated_at=one_user['updated_at']
                )
                success += 1
            except Exception as e:
                error += 1
                error_usernames.append(one_user['username'])

        obj_user = User.objects.all().values()
        users = list(obj_user)
        return JsonResponse({'code': 1, 'msg': '导入成功'})

class ExportUsersExcelView(APIView):
    def get(self, request):
        obj_user = User.objects.all().values()
        users = list(obj_user)
        if not users:
            return JsonResponse({'code': 0, 'msg': '无数据可导出'})

        excel_name = get_random_str() + ".xlsx"
        path = os.path.join(settings.MEDIA_ROOT, excel_name)
        os.makedirs(os.path.dirname(path), exist_ok=True)

        try:
            write_to_excel(users, path)
        except Exception as e:
            return JsonResponse({'code': 0, 'msg': '写入Excel文件失败，具体原因：' + str(e)})

        return JsonResponse({'code': 1, 'msg': '导出成功','name': excel_name})

def get_random_str():
    uuid_val = uuid.uuid4()
    uuid_str = str(uuid_val).encode('utf-8')
    md5 = hashlib.md5()
    md5.update(uuid_str)
    return md5.hexdigest()

def read_excel_dict(path: str):
    workbook = openpyxl.load_workbook(path)
    sheet = workbook.active
    users = []
    keys = ['username', 'email', 'phone', 'first_name', 'last_name', 'gender', 'created_at', 'updated_at']

    for row in list(sheet.iter_rows(values_only=True))[1:]:
        temp_dict = {}
        for index, cell in enumerate(row):
            if index < len(keys):
                temp_dict[keys[index]] = cell
        users.append(temp_dict)
    return users

def write_to_excel(data: list, path: str):
    workbook = openpyxl.Workbook()
    sheet = workbook.active
    sheet.title = 'users'

    if not data:
        raise ValueError("Data list is empty")

    keys = list(data[0].keys())

    for k, key in enumerate(keys, 1):
        sheet.cell(row=1, column=k, value=key)

    for index, item in enumerate(data, 2):
        for k, key in enumerate(keys, 1):
            sheet.cell(row=index, column=k, value=str(item[key]))

    workbook.save(path)
